/*

This file is part of Rooms3D.

Copyright (C) 2008 Pixecur Technologies Incorporated (Esotera).
Visit Esotera at http://www.esoteras3.com
 
Rooms3D is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3, or (at your option)
any later version.
 
Rooms3D is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
General Public License for more details.
 
You should have received a copy of the GNU General Public License
along with Rooms3D; see the file COPYING.  If not, write to 
Pixecur Technologies, 213-31 Peet Street, St. John's, NL, A1B 3W8. 
 
Linking this library statically or dynamically with other modules is
making a combined work based on this library.  Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
 
*/

package com.datasentinel.j3d.controls;

import java.awt.AWTEvent;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.Iterator;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;

import javax.media.j3d.BranchGroup;
import javax.media.j3d.Canvas3D;
import javax.media.j3d.Node;
import javax.media.j3d.PickInfo;

import com.datasentinel.j3d.controls.geom.ButtonBox;
import com.sun.j3d.utils.pickfast.PickCanvas;
import com.sun.j3d.utils.universe.SimpleUniverse;


public class J3DButton extends J3DComponent
{
	
	/**
	 * Component visual properties
	 */
	private Dimension3f size;


	/** A list of event listeners for this component. */
	protected Queue<ActionListener> listenerList = new ConcurrentLinkedQueue<ActionListener>();

	/**
	 * Component model
	 */
	private ButtonModel3D model;

	/**
	 * 
	 */
	private PickCanvas pickCanvas;
	
	public J3DButton(Canvas3D canvas3D, SimpleUniverse universe)
	{
		super(canvas3D, universe);
	}

	public J3DButton(Canvas3D canvas3D, SimpleUniverse universe, String text)
	{
		this(canvas3D, universe);
		this.model.setText(text);
	}

//	private void initializeDefaultValues()
//	{
//		this.size = ui.getDefaultSize();
//	}
	
	@Override
	protected J3DComponentUI createComponentUI()
	{
		return new J3DButtonUI();
	}
	
	protected void initializeComponent()
	{
		this.model = new ButtonModel3D();
		this.model.addChangeListener(changeListener);
		
		
		
		pickCanvas = new PickCanvas(canvas3D, universe.getLocale());
		pickCanvas.setFlags(PickInfo.NODE | PickInfo.CLOSEST_INTERSECTION_POINT);
		pickCanvas.setMode(PickInfo.PICK_GEOMETRY);
	}
	
	protected void initializeEventListeners()
	{
		canvas3D.addMouseListener(new MouseAdapter(){
			@Override
			public void mousePressed(MouseEvent e)
			{
				dispatchEvent(e);
			}
			
			@Override
			public void mouseReleased(MouseEvent e)
			{
				dispatchEvent(e);
			}
			
			@Override
			public void mouseClicked(MouseEvent e)
			{
				dispatchEvent(e);
			}
		});
		
	}

	public Dimension2f getSize()
	{
		return size;
	}

	public void setSize(Dimension2f size)
	{
		this.size = new Dimension3f(size, this.size.getDepth());
		changeListener.componentResized(null);
	}
	
	public ButtonModel3D getModel()
	{
		return model;
	}

//	public void renderComponent()
//	{
//		ui.render3DComponent(this);
//	}

	/**
	 * Adds an <code>ActionListener</code> to the button.
	 */
	public void addActionListener(ActionListener l)
	{
		listenerList.add(l);
	}

	/**
	 * Removes an <code>ActionListener</code> from the button. 
	 */
	public void removeActionListener(ActionListener l)
	{
		listenerList.remove(l);
	}

	protected void fireActionPerformed(ActionEvent event)
	{
		Iterator<ActionListener> listeners = listenerList.iterator();
		ActionEvent e = null;
		while (listeners.hasNext())
		{
			// Lazily create the event:
			if (e == null)
			{
				String actionCommand = event.getActionCommand();
				e = new ActionEvent(J3DButton.this,
						ActionEvent.ACTION_PERFORMED, actionCommand, event
								.getWhen(), event.getModifiers());
			}
			listeners.next().actionPerformed(e);
		}
	}
	
	private boolean isPointOnFrontShape(Point mousePosition)
	{
		pickCanvas.setShapeLocation(mousePosition.x, mousePosition.y);
		try
		{
			if (pickCanvas.getBranchGroup() != null)
			{
				PickInfo[] picks = pickCanvas.pickAllSorted();
				if (null != picks)
				{
					for (PickInfo pickInfo : picks)
					{
						Node node = pickInfo.getNode();
						if (node.getParent() instanceof ButtonBox)
						{
							if(node.getUserData() != null && node.getUserData().equals(ButtonBox.BUTTON_FRONT_SHAPE_NAME))
							{
								
								return true;
							}
						}
					}
				}
			}
		}
		catch (Exception e)
		{
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return false;
	}
	
    public void dispatchEvent(AWTEvent e) 
    {

    	if(e instanceof MouseEvent)
    	{
    		MouseEvent mouseEvent = (MouseEvent)e;
    		
			Point mousePosition = mouseEvent.getPoint();
			
			switch(mouseEvent.getID())
			{
				case MouseEvent.MOUSE_PRESSED:
					//if(isPointOnFrontShape(mousePosition))
						getModel().setPressed(true);					
					break;
				case MouseEvent.MOUSE_RELEASED:
					if(getModel().isPressed())
						getModel().setPressed(false);
					break;
				case MouseEvent.MOUSE_CLICKED:
					if(!listenerList.isEmpty())
					{
						if(isPointOnFrontShape(mousePosition))
						{
							fireActionPerformed(new ActionEvent(J3DButton.this,
			                        ActionEvent.ACTION_PERFORMED,
			                        null,
			                        mouseEvent.getWhen(),
			                        mouseEvent.getModifiers()));
						}
						
					}
					break;
			}
			
    	}
    }


	
    
    
//    /**
//     * 
//     */
//    
//    class EventHandler implements ActionListener, ChangeListener, ItemListener, ComponentListener{
//
//
//		@Override
//		public void actionPerformed(ActionEvent e)
//		{
//			
//		}
//
//		@Override
//		public void stateChanged(ChangeEvent e)
//		{
//			renderComponent();
//		}
//
//		@Override
//		public void itemStateChanged(ItemEvent e)
//		{
//			
//		}
//
//		@Override
//		public void componentHidden(ComponentEvent e)
//		{
//			// TODO Auto-generated method stub
//			
//		}
//
//		@Override
//		public void componentMoved(ComponentEvent e)
//		{
//			// TODO Auto-generated method stub
//			
//		}
//
//		@Override
//		public void componentResized(ComponentEvent e)
//		{
//			renderComponent();
//		}
//
//		@Override
//		public void componentShown(ComponentEvent e)
//		{
//			// TODO Auto-generated method stub
//			
//		}
//    	
//    }
//    
    
}
